﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace DbFactory.Base
{
    public class BaseRepository<T> : IBaseRepository<T> where T : BaseModel
    {

        public IDatabaseConnection connection = ConnectionFactory.createConnetction("mysql");

        public BaseRepository()
        {
        }

        public void add(T m)
        {
            try
            {
                connection.connect();
                connection.insert<T>(m);
                connection.disconnect();
            }
            catch (Exception)
            {
                if(connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }

        public async Task addAsync(T m)
        {
            try
            {
                connection.connect();
                await connection.insertAsync<T>(m);
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
        }


        


        public void add(T m, DbTransaction transaction)
        {
            try
            {
                connection.connect();
                connection.insert<T>(m, transaction);
                connection.disconnect();
            }
            catch(Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }

        public async Task addAsync(T m, DbTransaction transaction)
        {
            try
            {
                connection.connect();
                await connection.insertAsync<T>(m, transaction);
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
        }


        public void update(T m)
        {
            try
            {
                connection.connect();
                connection.update<T>(m);
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }

        public void update(T m, DbTransaction transaction)
        {
            try
            {
                connection.connect();
                connection.update<T>(m, transaction);
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }


        public void delete(string id)
        {
            try
            {
                connection.connect();
                connection.delete<T>(id, "id");
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }


        public T getOne(string id)
        {
            try
            {
                connection.connect();
                T one = connection.QueryFirst<T>(id);
                connection.disconnect();
                return one;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
        }


        public T getOneWhere(string where)
        {
            try
            {
                connection.connect();
                T one = connection.QueryFirstWhere<T>(where);
                connection.disconnect();
                return one;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
        }


        public IEnumerable<T> getList(string where)
        {
            try
            {
                connection.connect();
                IEnumerable<T> list = connection.QueryList<T>(where);
                connection.disconnect();
                return list;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }


        public IEnumerable<T> getList(Expression<Func<T, bool>> expression)
        {
            try
            {
                connection.connect();
                IEnumerable<T> list = connection.QueryList<T>(expression);
                connection.disconnect();
                return list;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }

        public IEnumerable<T> getList(int page, int pageSize)
        {
            try
            {
                connection.connect();
                IEnumerable<T> list = connection.QueryList<T>(pageSize, page);
                connection.disconnect();
                return list;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }


        public IEnumerable<T> getList(string where, int page, int pageSize)
        {
            try
            {
                connection.connect();
                IEnumerable<T> list = connection.QueryList<T>(where, pageSize, page);
                connection.disconnect();
                return list;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }

        public IEnumerable<T> getList(Expression<Func<T, bool>> expression, int page, int pageSize)
        {
            try
            {
                connection.connect();
                IEnumerable<T> list = connection.QueryList<T>(expression, pageSize, page);
                connection.disconnect();
                return list;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }


        public int getCount(string where)
        {
            try
            {
                connection.connect();
                int count = connection.GetCount<T>(where);
                connection.disconnect();
                return count;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }



        public void createTable()
        {
            try
            {
                connection.connect();
                connection.CreateTable<T>();
                connection.disconnect();
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }

        public TableInfo getTableInfo()
        {
            try
            {
                string t = typeof(T).Name.ToLower();
                connection.connect();
                var rs = connection.GetTableInfo(t);
                connection.disconnect();
                return rs;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }


        public List<string> getTbNameList()
        {
            try
            {
                connection.connect();
                var rs = connection.GetTbNameList();
                connection.disconnect();
                return rs;
            }
            catch (Exception)
            {
                if (connection.connectState() != ConnectionState.Closed)
                {
                    connection.disconnect();
                }
                throw;
            }
            
        }
    }

}
